#pragma once
#include <iostream>
#include <queue>
#include <functional>
#include "Thread.hpp"
#include "ThreadPool.hpp"
#include "log.hpp"
#include "LockGuard.hpp"
#include <unistd.h>
#include "Task.hpp"

static const int defaultnum = 5;

class ThreadData
{
};

template <typename T>
class ThreadPool
{
public:
    ThreadPool(int thread_num = defaultnum)
        : _thread_nums(thread_num)
    {
        // 初始化锁和条件变量
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);

        // 先构建若干线程
        for (int i = 0; i < _thread_nums; i++)
        {
            // 创建线程并放入 容器中
            std::string threadname = "Thread-" + std::to_string(i + 1);

            T td;
            Thread<T> t(std::bind(&ThreadPool::ThreadRun, this, std::placeholders::_1), threadname, td);
            // Thread 的构造函数第一个参数为 指定调用函数，后面是函数名

            _threads.push_back(t);
        }
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

    void ThreadWait()
    {
        pthread_cond_wait(&_cond,&_mutex);
    }

    void ThreadWakeup()
    {
        pthread_cond_signal(&_cond);
    }

    // 线程需要处理的任务
    void ThreadRun(T &data)  //这个参数暂时没有用到
    {
        while (true)
        {
            T t ;
            {
                LockGuard LockGuard(&_mutex);
                //   pthread_mutex_lock(&_mutex);
                // std::cout << "Thread is running ..." << endl;

                while (_q.empty())
                { // 如果任务队列为空，那么在条件上进行等待
                    //pthread_cond_wait(_cond, &mutex);

                    ThreadWait();
                }
                t= _q.front(); // 拿任务
                _q.pop();

                //pthread_mutex_unlock(&_mutex);
            }

            // 运行任务
            t();
            cout<<"result: "<<t.PrintResult()<<endl;
            
        }
    }

    bool Start()
    {
        // 启动
        for (auto &thread : _threads)
        {
            thread.Start();
        }
    }

    void Push(const T &in)
    {
        {
            LockGuard lockguard(&_mutex);
            _q.push(in);
            ThreadWakeup();
        }

    }

    void Wait()
    {
        for (auto &thread : _threads)
        {
            thread.Join();
        }
    }

public:
    std::queue<T> _q;
    std::vector<Thread<T>> _threads; // 放线程
    int _thread_nums;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;

    // load   定义负载负载，如果线程不够，可以动态增加，线程等待过多，可以释放掉一些资源
    // int numeber{1};

    int _thread_num_low_water;     //进程数量低水位线
    int _thread_num_high_water;    //进程数量高水位线

    int _task_num_low_water;    //任务数量低水位线
    int _task_num_high_wate;    //任务数量低水位线
};